
#pragma once

using namespace System::ComponentModel;
using namespace System::Collections::Generic;

#include "DeviceInfo.h"
#include "../Pipelines/PipelineSet.h"
#include "../Parameters/ParameterTree.h"

namespace ttg_internal
{
	namespace utils
	{
		///<summary>
		/// Contains global information (about pipeline, devices, etc).
		///</summary>
		public ref class GlobalInfo : public System::ICloneable
		{
			private:
				BindingList<DeviceInfo ^> ^_devices;
				ParameterTree ^_parameters;
				PipelineSet ^_pipelines;
			internal:
				///<summary>
				/// Creates empty global information.
				///</summary>
				GlobalInfo()
				{
					_devices = gcnew BindingList<DeviceInfo ^>();
					_parameters = gcnew ParameterTree();
					_pipelines = gcnew PipelineSet();
				}
				///<summary>
				/// Returns existent info for device with given name (or nullptr).
				///</summary>
				DeviceInfo ^GetDeviceInfo(System::String ^name)
				{
					for each (DeviceInfo ^device in _devices)
						if (device->Name == name)
							return device;
					return nullptr;
				}
				///<summary>
				/// Registers given device info.
				///</summary>
				void AddDeviceInfo(DeviceInfo ^info)
				{
					if (info != nullptr)
						_devices->Add(info);
				}
			public:
				///<summary>
				/// Returns collection with devices.
				///</summary>
				property BindingList<DeviceInfo ^> ^Devices
				{
					BindingList<DeviceInfo ^> ^get()
					{ return _devices; }
				}
				///<summary>
				/// Returns tree of parameters.
				///</summary>
				property ParameterTree ^Parameters
				{
					ParameterTree ^get()
					{ return _parameters; }
				}
				///<summary>
				/// Returns set with all pipelines.
				///</summary>
				property PipelineSet ^Pipelines
				{
					PipelineSet ^get()
					{ return _pipelines; }
				}
				///<summary>
				/// Locks information. Should be called in GUI thread (if necessary).
				///</summary>
				void Lock()
				{
					System::Threading::Monitor::Enter(this);
				}
				///<summary>
				/// Unlocks information.
				///</summary>
				void UnLock()
				{
					System::Threading::Monitor::Exit(this);
				}
				virtual Object ^Clone()
				{
					GlobalInfo ^gi = gcnew GlobalInfo();
					for each (DeviceInfo ^di in Devices)
					{
						gi->AddDeviceInfo((DeviceInfo ^)di->Clone());
					}
					return gi;
				}
		};
	}
}
